package com.wei.health.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wei.health.mapper.TBodyInfoMapper;
import com.wei.health.mapper.THealthConfigMapper;
import com.wei.health.model.dto.BodyInfoQuery;
import com.wei.health.model.dto.BodyInfoSaveDto;
import com.wei.health.model.entity.TBodyInfo;
import com.wei.health.model.vo.BodyInfoDetailVo;
import com.wei.health.model.vo.BodyInfoStatisticsVo;
import com.wei.health.model.vo.BodyInfoStatisticsVo.BodyInfoVo;
import com.wei.health.model.vo.BusinessException;
import com.wei.health.model.vo.PageVo;
import com.wei.health.service.HealthService;
import com.wei.health.util.DateUtils;
import com.wei.health.util.PublicUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class HealthServiceImpl implements HealthService {

	@Autowired
	private THealthConfigMapper healthConfigMapper;
	@Autowired
	private TBodyInfoMapper bodyInfoMapper;

	@Override
	@Transactional
	public void saveBodyInfo(int userId, BodyInfoSaveDto bodyInfoSaveDto) {
		// 判断今天是否已经录入过
		final int countByOneAsToDay = bodyInfoMapper.countByOneAsToDay(userId);
		if (countByOneAsToDay > 0)
			throw new BusinessException("今天已经打过卡了");

		final TBodyInfo tBodyInfo = new TBodyInfo();
		PublicUtils.copyBean(bodyInfoSaveDto, tBodyInfo);
		tBodyInfo.init(userId,tBodyInfo.getNickName());
		bodyInfoMapper.insertByOne(tBodyInfo);
	}

	@Override
	public PageVo<TBodyInfo> bodyInfoList(int userId, BodyInfoQuery bodyInfoQuery) {
		if ((bodyInfoQuery.getMinDate() != null) && (bodyInfoQuery.getMaxDate() != null)) {
			if (bodyInfoQuery.getMinDate().after(bodyInfoQuery.getMaxDate()))
				throw new BusinessException("最小时间不能大于最大时间");
		}
		PageHelper.startPage(bodyInfoQuery.getPage(), bodyInfoQuery.getPageSize());
		final PageInfo<TBodyInfo> pageInfo = new PageInfo<>(
				bodyInfoMapper.selectByUserId(userId, bodyInfoQuery.getMinDate(), bodyInfoQuery.getMaxDate()));
		return PageVo.of(pageInfo);
	}

	@Override
	public PageVo<TBodyInfo> userRegisList(BodyInfoQuery bodyInfoQuery) {
		if ((bodyInfoQuery.getMinDate() != null) && (bodyInfoQuery.getMaxDate() != null)) {
			if (bodyInfoQuery.getMinDate().after(bodyInfoQuery.getMaxDate()))
				throw new BusinessException("最小时间不能大于最大时间");
		}
		PageHelper.startPage(bodyInfoQuery.getPage(), bodyInfoQuery.getPageSize());
		final PageInfo<TBodyInfo> pageInfo = new PageInfo<>(
				bodyInfoMapper.userRegisList(bodyInfoQuery.getMinDate(), bodyInfoQuery.getMaxDate()));
		return PageVo.of(pageInfo);
	}

	@Override
	@Transactional
	public void deleteBodyInfo(int userId, int id) {
		bodyInfoMapper.deleteByOne(id, userId);
	}

	@Override
	public BodyInfoDetailVo getBodyInfo(int userId, int id) {
		final TBodyInfo bodyInfo = bodyInfoMapper.selectByUserOne(id, userId);
		if (bodyInfo == null)
			throw new BusinessException("该身体信息不存在");

		BodyInfoDetailVo bodyInfoDetailVo = new BodyInfoDetailVo();
		PublicUtils.copyBean(bodyInfo, bodyInfoDetailVo);
		bodyInfoDetailVo = bodyInfoCompare(bodyInfoDetailVo);
		return bodyInfoDetailVo;
	}

	/** 健康信息比较 **/
	private BodyInfoDetailVo bodyInfoCompare(BodyInfoDetailVo bodyInfoDetailVo) {
		// TODO
		// 血压
		bodyInfoDetailVo = bloodPressureCompare(bodyInfoDetailVo);
		// 心率
		final int heartRate = bodyInfoDetailVo.getHeartRate();
		bodyInfoDetailVo.setHeartRateStatus(heartRateStatus(heartRate));
		bodyInfoDetailVo.setHeartRateDesc(statusDesc(bodyInfoDetailVo.getHeartRateStatus()));
		// 体温
		final double temperature = bodyInfoDetailVo.getTemperature();
		bodyInfoDetailVo.setTemperatureStatus(temperatureStatus(temperature));
		bodyInfoDetailVo.setTemperatureDesc(statusDesc(bodyInfoDetailVo.getTemperatureStatus()));
		return bodyInfoDetailVo;
	}

	/** 血压判断 **/
	private BodyInfoDetailVo bloodPressureCompare(BodyInfoDetailVo bodyInfoDetailVo) {
		// 收缩压
		// 正常范围收缩压90～139mmHg
		final int minHighBloodPressure = 90;
		final int maxHighBloodPressure = 139;
		// 舒张压
		// 舒张压60～89mmHg
		final int minLowBloodPressure = 60;
		final int maxLowBloodPressure = 89;
		// 高血压：成人收缩压≥140mmHg和（或）舒张压≥90mmHg
		// 低血压：血压低于90/60mmHg

		if (bodyInfoDetailVo.getLowBloodPressure() > maxLowBloodPressure) {
			bodyInfoDetailVo.setLowBloodPressureStatus(1);
			bodyInfoDetailVo.setLowBloodPressureDesc(statusDesc(bodyInfoDetailVo.getLowBloodPressureStatus()));
		} else if (bodyInfoDetailVo.getLowBloodPressure() < minLowBloodPressure) {
			bodyInfoDetailVo.setLowBloodPressureStatus(-1);
			bodyInfoDetailVo.setLowBloodPressureDesc(statusDesc(bodyInfoDetailVo.getLowBloodPressureStatus()));
		} else {
			bodyInfoDetailVo.setLowBloodPressureDesc(statusDesc(bodyInfoDetailVo.getLowBloodPressureStatus()));
		}

		if (bodyInfoDetailVo.getHighBloodPressure() > maxHighBloodPressure) {
			bodyInfoDetailVo.setHighBloodPressureStatus(1);
			bodyInfoDetailVo.setHighBloodPressureDesc(statusDesc(bodyInfoDetailVo.getHighBloodPressureStatus()));
		} else if (bodyInfoDetailVo.getHighBloodPressure() < minHighBloodPressure) {
			bodyInfoDetailVo.setHighBloodPressureStatus(-1);
			bodyInfoDetailVo.setHighBloodPressureDesc(statusDesc(bodyInfoDetailVo.getHighBloodPressureStatus()));
		} else {
			bodyInfoDetailVo.setHighBloodPressureDesc(statusDesc(bodyInfoDetailVo.getHighBloodPressureStatus()));
		}

		if ((bodyInfoDetailVo.getLowBloodPressureStatus() == 1)
				&& (bodyInfoDetailVo.getHighBloodPressureStatus() == 1)) {
			bodyInfoDetailVo.setBloodPressureDesc("该用户为高血压");
		} else if ((bodyInfoDetailVo.getLowBloodPressureStatus() == -1)
				&& (bodyInfoDetailVo.getHighBloodPressureStatus() == -1)) {
			bodyInfoDetailVo.setBloodPressureDesc("该用户为低血压");
		} else if ((bodyInfoDetailVo.getLowBloodPressureStatus() == 0)
				&& (bodyInfoDetailVo.getHighBloodPressureStatus() == 0)) {
			bodyInfoDetailVo.setBloodPressureDesc("该用户血压正常");
		}

		/*
		 * if ((bodyInfoDetailVo.getLowBloodPressure() > maxLowBloodPressure) ||
		 * (bodyInfoDetailVo.getHighBloodPressure() > maxHighBloodPressure)) {
		 * bodyInfoDetailVo.setLowBloodPressureStatus(1);
		 * bodyInfoDetailVo.setLowBloodPressureDesc(statusDesc(bodyInfoDetailVo.
		 * getLowBloodPressureStatus()));
		 * bodyInfoDetailVo.setHighBloodPressureStatus(1);
		 * bodyInfoDetailVo.setHighBloodPressureDesc(statusDesc(bodyInfoDetailVo.
		 * getHighBloodPressureStatus())); } else if
		 * ((bodyInfoDetailVo.getLowBloodPressure() < minLowBloodPressure) ||
		 * (bodyInfoDetailVo.getHighBloodPressure() < minHighBloodPressure)) {
		 * bodyInfoDetailVo.setLowBloodPressureStatus(-1);
		 * bodyInfoDetailVo.setLowBloodPressureDesc(statusDesc(bodyInfoDetailVo.
		 * getLowBloodPressureStatus()));
		 * bodyInfoDetailVo.setHighBloodPressureStatus(-1);
		 * bodyInfoDetailVo.setHighBloodPressureDesc(statusDesc(bodyInfoDetailVo.
		 * getHighBloodPressureStatus())); } else {
		 * bodyInfoDetailVo.setLowBloodPressureDesc(statusDesc(bodyInfoDetailVo.
		 * getLowBloodPressureStatus()));
		 * bodyInfoDetailVo.setHighBloodPressureDesc(statusDesc(bodyInfoDetailVo.
		 * getHighBloodPressureStatus())); }
		 */
		return bodyInfoDetailVo;
	}

	/** 心率判断 **/
	private int heartRateStatus(int heartRate) {
		final int min = 60;
		final int max = 80;
		final int max1 = 100;
		final int max2 = 120;
		if (heartRate < min)
			return -1;
		else if ((heartRate >= min) && (heartRate <= max))
			return 0;
		else if ((heartRate > max) && (heartRate < max1))
			return 1;
		else if ((heartRate > max1) && (heartRate < max2))
			return 2;
		else
			return 4;
	}

	/** 体温判断 **/
	private int temperatureStatus(double temperature) {
		final Double min = 36.1;
		final Double max = 37.3;
		final Double max1 = 38.1;
		final Double max2 = 39.1;
		final Double max3 = 41.1;
		if (temperature < min)
			return -1;
		else if ((temperature >= min) && (temperature <= max))
			return 0;
		else if ((temperature > max) && (temperature < max1))
			return 1;
		else if ((temperature > max1) && (temperature < max2))
			return 2;
		else if ((temperature > max2) && (temperature < max3))
			return 3;
		else
			return 4;
	}

	/** 状态描述语 **/
	private String statusDesc(int status) {
		switch (status) {
		case -1:
			return "低";
		case 1:
			return "高";
		case 2:
			return "很高";
		case 3:
			return "严重";
		case 4:
			return "非常严重";
		default:
			return "正常";
		}
	}

	@Override
	public BodyInfoStatisticsVo getBodyStatistics(int userId, Date date) {
		LocalDateTime now = null;
		if (date == null) {
			now = LocalDateTime.now();
		} else {
			now = DateUtils.convertDateToLDT(date);
		}
		final LocalDateTime startWeekDateTime = DateUtils.getDayStart(DateUtils.getWeekBegin(now));
		final Date startWeek = DateUtils.convertLDTToDate(startWeekDateTime);
		final Date endWeek = DateUtils.convertLDTToDate(DateUtils.getDayEnd(DateUtils.getWeekEnd(now)));
		final List<TBodyInfo> bodyInfos = bodyInfoMapper.selectByUserId(userId, startWeek, endWeek);

		final List<BodyInfoVo> bodyInfoVos = fillBodyInfoVo(startWeekDateTime, bodyInfos);

		return new BodyInfoStatisticsVo(bodyInfoVos.stream().map(BodyInfoVo::getTypeName).collect(Collectors.toList()),
				bodyInfoVos);
	}

	/** 填充数据 **/
	private List<BodyInfoVo> fillBodyInfoVo(LocalDateTime startWeekDateTime, List<TBodyInfo> bodyInfos) {
		final List<BodyInfoVo> bodyInfoVos = new ArrayList<>();
		final List<Object> healths = new ArrayList<>();
		final List<Object> goOuts = new ArrayList<>();
		final List<Object> workStates = new ArrayList<>();
		final List<Object> temperatures = new ArrayList<>();
		final List<Object> Notices = new ArrayList<>();
		for (int i = 0; i < 7; i++) {
			final Long targetTime = DateUtils.getMilliByTime(DateUtils.plus(startWeekDateTime, i, ChronoUnit.DAYS));
			boolean isSign = false;
			for (final TBodyInfo tBodyInfo : bodyInfos) {
				if (targetTime.equals(DateUtils.getMilliByTime(
						DateUtils.getDayStart(DateUtils.convertDateToLDT(tBodyInfo.getCreateTime()))))) {
					// 已打卡
					isSign = true;
					healths.add(tBodyInfo.getHealth());
					goOuts.add(tBodyInfo.getGoOut());
					workStates.add(tBodyInfo.getWorkState());
					temperatures.add(tBodyInfo.getTemperature());
					Notices.add(tBodyInfo.getNotice());
					break;
				}
			}
			if (!isSign) {
				// 未打卡
				healths.add(0);
				goOuts.add(0);
				workStates.add(0);
				temperatures.add(0);
				Notices.add(0);
			}
		}
		List<String> list = new ArrayList<>();
		bodyInfoVos.add(new BodyInfoVo("健康状态", healths));
		bodyInfoVos.add(new BodyInfoVo("外出状态", goOuts));
		bodyInfoVos.add(new BodyInfoVo("工作状态", workStates));
		bodyInfoVos.add(new BodyInfoVo("体温", temperatures));
		bodyInfoVos.add(new BodyInfoVo("备注", Notices));

		return bodyInfoVos;
	}

}